home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / libtiff / tif_getimage.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  29KB  |  1,216 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_getimage.c,v 1.18 93/06/28 16:17:45 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. /*
  30.  * TIFF Library
  31.  *
  32.  * Read and return a packed RGBA image.
  33.  */
  34. #include "tiffiop.h"
  35.  
  36. typedef    u_char RGBvalue;
  37.  
  38. static    u_long width, height;        /* image width & height */
  39. static    u_short bitspersample;
  40. static    u_short samplesperpixel;
  41. static    u_short photometric;
  42. static    u_short orientation;
  43. static    u_short matting;
  44. static    u_short planarconfig;
  45. /* colormap for pallete images */
  46. static    u_short *redcmap, *greencmap, *bluecmap;
  47. static    int stoponerr;            /* stop on read error */
  48. /* YCbCr support */
  49. static    u_short YCbCrHorizSampling;
  50. static    u_short YCbCrVertSampling;
  51. static    float *YCbCrCoeffs;
  52. static    float *refBlackWhite;
  53.  
  54. static    u_long **BWmap;
  55. static    u_long **PALmap;
  56.  
  57. #if USE_PROTOTYPES
  58. static    int gt(TIFF*, int, int, u_long*);
  59. static    int gtTileContig(TIFF*, u_long*, RGBvalue*, u_long, u_long);
  60. static    int gtTileSeparate(TIFF*, u_long*, RGBvalue*, u_long, u_long);
  61. static    int gtStripContig(TIFF*, u_long*, RGBvalue*, u_long, u_long);
  62. static    int gtStripSeparate(TIFF*, u_long*, RGBvalue*, u_long, u_long);
  63. static    int makebwmap(TIFF*, RGBvalue*);
  64. static    int makecmap(TIFF*, u_short*, u_short*, u_short*);
  65. #else
  66. static    int gt();
  67. static    int gtTileContig();
  68. static    int gtTileSeparate();
  69. static    int gtStripContig();
  70. static    int gtStripSeparate();
  71. static    int makebwmap();
  72. static    int makecmap();
  73. #endif
  74. static    void initYCbCrConversion();
  75.  
  76. int
  77. DECLARE5(TIFFReadRGBAImage,
  78.     TIFF*, tif, u_long, rwidth, u_long, rheight, u_long*, raster, int, stop)
  79. {
  80.     int ok;
  81.     u_long width, height;
  82.  
  83.     TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
  84.     switch (bitspersample) {
  85.     case 1: case 2: case 4:
  86.     case 8: case 16:
  87.         break;
  88.     default:
  89.         TIFFError(TIFFFileName(tif),
  90.             "Sorry, can not handle %d-bit images", bitspersample);
  91.         return (0);
  92.     }
  93.     TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
  94.     if (samplesperpixel > 4) {
  95.         TIFFError(TIFFFileName(tif),
  96.             "Sorry, can not handle images with %d-samples/pixel",
  97.             samplesperpixel);
  98.         return (0);
  99.     }
  100.     TIFFGetFieldDefaulted(tif, TIFFTAG_MATTEING, &matting);
  101.     TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
  102.     switch (samplesperpixel - matting) {
  103.     case 3:
  104.         break;
  105.     case 1: case 4:
  106. /* XXX */
  107.         if (!matting || planarconfig != PLANARCONFIG_CONTIG)
  108.             break;
  109.         /* fall thru... */
  110.     default:
  111.         TIFFError(TIFFFileName(tif),
  112.             "Sorry, can not handle %d-channel %s images%s",
  113.             samplesperpixel,
  114.             planarconfig == PLANARCONFIG_CONTIG ?
  115.             "packed" : "separated",
  116.             matting ? " with alpha" : "");
  117.         return (0);
  118.     }
  119.     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
  120.         switch (samplesperpixel) {
  121.         case 1:
  122.             photometric = PHOTOMETRIC_MINISBLACK;
  123.             break;
  124.         case 3: case 4:
  125.             photometric = PHOTOMETRIC_RGB;
  126.             break;
  127.         default:
  128.             TIFFError(TIFFFileName(tif),
  129.                 "Missing needed \"PhotometricInterpretation\" tag");
  130.             return (0);
  131.         }
  132.         TIFFError(TIFFFileName(tif),
  133.             "No \"PhotometricInterpretation\" tag, assuming %s\n",
  134.             photometric == PHOTOMETRIC_RGB ? "RGB" : "min-is-black");
  135.     }
  136.     switch (photometric) {
  137.     case PHOTOMETRIC_MINISWHITE:
  138.     case PHOTOMETRIC_MINISBLACK:
  139.     case PHOTOMETRIC_RGB:
  140.     case PHOTOMETRIC_PALETTE:
  141.     case PHOTOMETRIC_YCBCR:
  142.         break;
  143.     case PHOTOMETRIC_SEPARATED: {
  144.         u_short inkset;
  145.         TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
  146.         if (inkset != INKSET_CMYK) {
  147.             TIFFError(TIFFFileName(tif),
  148.                 "Sorry, can not handle separated image with %s=%d",
  149.                 "InkSet", inkset);
  150.             return (0);
  151.         }
  152.         break;
  153.     }
  154.     default:
  155.         TIFFError(TIFFFileName(tif),
  156.             "Sorry, can not handle image with %s=%d",
  157.             "PhotometricInterpretation", photometric);
  158.         return (0);
  159.     }
  160.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
  161.     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
  162.     /* XXX verify rwidth and rheight against width and height */
  163.     stoponerr = stop;
  164.     BWmap = NULL;
  165.     PALmap = NULL;
  166.     ok = gt(tif, rwidth, height, raster + (rheight-height)*rwidth);
  167.     if (BWmap)
  168.         _TIFFfree((char *)BWmap);
  169.     if (PALmap)
  170.         _TIFFfree((char *)PALmap);
  171.     return (ok);
  172. }
  173.  
  174. static int
  175. DECLARE4(checkcmap, int, n, u_short*, r, u_short*, g, u_short*, b)
  176. {
  177.     while (n-- > 0)
  178.         if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
  179.             return (16);
  180.     return (8);
  181. }
  182.  
  183. /*
  184.  * Construct a mapping table to convert from the range
  185.  * of the data samples to [0,255] --for display.  This
  186.  * process also handles inverting B&W images when needed.
  187.  */ 
  188. static int
  189. DECLARE4(setupMap,
  190.     TIFF*, tif,
  191.     u_short, minsamplevalue, u_short, maxsamplevalue,
  192.     RGBvalue**, pMap
  193. )
  194. {
  195.     register int x, range;
  196.     RGBvalue *Map;
  197.  
  198.     range = maxsamplevalue - minsamplevalue;
  199.     Map = (RGBvalue *)_TIFFmalloc((range + 1) * sizeof (RGBvalue));
  200.     if (Map == NULL) {
  201.         TIFFError(TIFFFileName(tif),
  202.             "No space for photometric conversion table");
  203.         return (0);
  204.     }
  205.     if (photometric == PHOTOMETRIC_MINISWHITE) {
  206.         for (x = 0; x <= range; x++)
  207.             Map[x] = ((range - x) * 255) / range;
  208.     } else {
  209.         for (x = 0; x <= range; x++)
  210.             Map[x] = (x * 255) / range;
  211.     }
  212.     if (bitspersample <= 8 &&
  213.         (photometric == PHOTOMETRIC_MINISBLACK ||
  214.          photometric == PHOTOMETRIC_MINISWHITE)) {
  215.         /*
  216.          * Use photometric mapping table to construct
  217.          * unpacking tables for samples <= 8 bits.
  218.          */
  219.         if (!makebwmap(tif, Map))
  220.             return (0);
  221.         /* no longer need Map, free it */
  222.         _TIFFfree((char *)Map);
  223.         Map = NULL;
  224.     }
  225.     *pMap = Map;
  226.     return (1);
  227. }
  228.  
  229. static int
  230. DECLARE4(gt, TIFF*, tif, int, w, int, h, u_long*, raster)
  231. {
  232.     u_short minsamplevalue, maxsamplevalue;
  233.     RGBvalue *Map;
  234.     int e, ncomps;
  235.  
  236.     TIFFGetFieldDefaulted(tif, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue);
  237.     TIFFGetFieldDefaulted(tif, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue);
  238.     Map = NULL;
  239.     switch (photometric) {
  240.     case PHOTOMETRIC_YCBCR:
  241.         TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS,
  242.             &YCbCrCoeffs);
  243.         TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
  244.             &YCbCrHorizSampling, &YCbCrVertSampling);
  245.         TIFFGetFieldDefaulted(tif, TIFFTAG_REFERENCEBLACKWHITE,
  246.             &refBlackWhite);
  247.         initYCbCrConversion();
  248.         /* fall thru... */
  249.     case PHOTOMETRIC_RGB:
  250.     case PHOTOMETRIC_SEPARATED:
  251.         if (minsamplevalue == 0 && maxsamplevalue == 255)
  252.             break;
  253.         /* fall thru... */
  254.     case PHOTOMETRIC_MINISBLACK:
  255.     case PHOTOMETRIC_MINISWHITE:
  256.         if (!setupMap(tif, minsamplevalue, maxsamplevalue, &Map))
  257.             return (0);
  258.         break;
  259.     case PHOTOMETRIC_PALETTE:
  260.         if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
  261.                   &redcmap, &greencmap, &bluecmap)) {
  262.             TIFFError(TIFFFileName(tif),
  263.                 "Missing required \"Colormap\" tag");
  264.             return (0);
  265.         }
  266.         /*
  267.          * Convert 16-bit colormap to 8-bit (unless it looks
  268.          * like an old-style 8-bit colormap).
  269.          */
  270.         if (checkcmap(1<<bitspersample, redcmap, greencmap, bluecmap) == 16) {
  271.             int i;
  272.             for (i = (1<<bitspersample)-1; i > 0; i--) {
  273. #define    CVT(x)        (((x) * 255) / ((1L<<16)-1))
  274.                 redcmap[i] = CVT(redcmap[i]);
  275.                 greencmap[i] = CVT(greencmap[i]);
  276.                 bluecmap[i] = CVT(bluecmap[i]);
  277.             }
  278.         } else
  279.             TIFFWarning(TIFFFileName(tif), "Assuming 8-bit colormap");
  280.         if (bitspersample <= 8) {
  281.             /*
  282.              * Use mapping table and colormap to construct
  283.              * unpacking tables for samples < 8 bits.
  284.              */
  285.             if (!makecmap(tif, redcmap, greencmap, bluecmap))
  286.                 return (0);
  287.         }
  288.         break;
  289.     }
  290.     ncomps = samplesperpixel - matting;
  291.     if (planarconfig == PLANARCONFIG_SEPARATE && ncomps > 1) {
  292.         e = TIFFIsTiled(tif) ?
  293.             gtTileSeparate(tif, raster, Map, h, w) :
  294.             gtStripSeparate(tif, raster, Map, h, w);
  295.     } else {
  296.         e = TIFFIsTiled(tif) ? 
  297.             gtTileContig(tif, raster, Map, h, w) :
  298.             gtStripContig(tif, raster, Map, h, w);
  299.     }
  300.     if (Map)
  301.         _TIFFfree((char *)Map);
  302.     return (e);
  303. }
  304.  
  305. static u_long
  306. DECLARE2(setorientation, TIFF*, tif, u_long, h)
  307. {
  308.     u_long y;
  309.  
  310.     TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation);
  311.     switch (orientation) {
  312.     case ORIENTATION_BOTRIGHT:
  313.     case ORIENTATION_RIGHTBOT:    /* XXX */
  314.     case ORIENTATION_LEFTBOT:    /* XXX */
  315.         TIFFWarning(TIFFFileName(tif), "using bottom-left orientation");
  316.         orientation = ORIENTATION_BOTLEFT;
  317.         /* fall thru... */
  318.     case ORIENTATION_BOTLEFT:
  319.         y = 0;
  320.         break;
  321.     case ORIENTATION_TOPRIGHT:
  322.     case ORIENTATION_RIGHTTOP:    /* XXX */
  323.     case ORIENTATION_LEFTTOP:    /* XXX */
  324.     default:
  325.         TIFFWarning(TIFFFileName(tif), "using top-left orientation");
  326.         orientation = ORIENTATION_TOPLEFT;
  327.         /* fall thru... */
  328.     case ORIENTATION_TOPLEFT:
  329.         y = h-1;
  330.         break;
  331.     }
  332.     return (y);
  333. }
  334.  
  335. #if USE_PROTOTYPES
  336. typedef void (*tileContigRoutine)
  337.     (u_long*, u_char*, RGBvalue*, u_long, u_long, int, int);
  338. static tileContigRoutine pickTileContigCase(TIFF*, RGBvalue*);
  339. #else
  340. typedef void (*tileContigRoutine)();
  341. static tileContigRoutine pickTileContigCase();
  342. #endif
  343.  
  344. /*
  345.  * Get an tile-organized image that has
  346.  *    PlanarConfiguration contiguous if SamplesPerPixel > 1
  347.  * or
  348.  *    SamplesPerPixel == 1
  349.  */    
  350. static int
  351. DECLARE5(gtTileContig,
  352.     TIFF*, tif, u_long*, raster, RGBvalue*, Map, u_long, h, u_long, w)
  353. {
  354.     u_long col, row, y;
  355.     u_long tw, th;
  356.     u_char *buf;
  357.     int fromskew, toskew;
  358.     u_int nrow;
  359.     tileContigRoutine put;
  360.  
  361.     put = pickTileContigCase(tif, Map);
  362.     if (put == 0)
  363.         return (0);
  364.     buf = (u_char *)_TIFFmalloc(TIFFTileSize(tif));
  365.     if (buf == 0) {
  366.         TIFFError(TIFFFileName(tif), "No space for tile buffer");
  367.         return (0);
  368.     }
  369.     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
  370.     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
  371.     y = setorientation(tif, h);
  372.     toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w);
  373.     for (row = 0; row < h; row += th) {
  374.         nrow = (row + th > h ? h - row : th);
  375.         for (col = 0; col < w; col += tw) {
  376.             if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0 &&
  377.                 stoponerr)
  378.                 break;
  379.             if (col + tw > w) {
  380.                 /*
  381.                  * Tile is clipped horizontally.  Calculate
  382.                  * visible portion and skewing factors.
  383.                  */
  384.                 u_long npix = w - col;
  385.                 fromskew = tw - npix;
  386.                 (*put)(raster + y*w + col, buf, Map,
  387.                     npix, nrow, fromskew, toskew + fromskew);
  388.             } else
  389.                 (*put)(raster + y*w + col, buf, Map,
  390.                     tw, nrow, 0, toskew);
  391.         }
  392.         y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
  393.     }
  394.     _TIFFfree(buf);
  395.     return (1);
  396. }
  397.  
  398. #if USE_PROTOTYPES
  399. typedef void (*tileSeparateRoutine)
  400.     (u_long*, u_char*, u_char*, u_char*, RGBvalue*, u_long, u_long, int, int);
  401. static tileSeparateRoutine pickTileSeparateCase(TIFF*, RGBvalue*);
  402. #else
  403. typedef void (*tileSeparateRoutine)();
  404. static tileSeparateRoutine pickTileSeparateCase();
  405. #endif
  406.  
  407. /*
  408.  * Get an tile-organized image that has
  409.  *     SamplesPerPixel > 1
  410.  *     PlanarConfiguration separated
  411.  * We assume that all such images are RGB.
  412.  */    
  413. static int
  414. DECLARE5(gtTileSeparate,
  415.     TIFF*, tif, u_long*, raster, RGBvalue*, Map, u_long, h, u_long, w)
  416. {
  417.     u_long col, row, y;
  418.     u_long tw, th;
  419.     u_char *buf;
  420.     u_char *r, *g, *b;
  421.     u_long tilesize;
  422.     int fromskew, toskew;
  423.     u_int nrow;
  424.     tileSeparateRoutine put;
  425.  
  426.     put = pickTileSeparateCase(tif, Map);
  427.     if (put == 0)
  428.         return (0);
  429.     tilesize = TIFFTileSize(tif);
  430.     buf = (u_char *)_TIFFmalloc(3*tilesize);
  431.     if (buf == 0) {
  432.         TIFFError(TIFFFileName(tif), "No space for tile buffer");
  433.         return (0);
  434.     }
  435.     r = buf;
  436.     g = r + tilesize;
  437.     b = g + tilesize;
  438.     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
  439.     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
  440.     y = setorientation(tif, h);
  441.     toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w);
  442.     for (row = 0; row < h; row += th) {
  443.         nrow = (row + th > h ? h - row : th);
  444.         for (col = 0; col < w; col += tw) {
  445.             if (TIFFReadTile(tif, r, col, row,0,0) < 0 && stoponerr)
  446.                 break;
  447.             if (TIFFReadTile(tif, g, col, row,0,1) < 0 && stoponerr)
  448.                 break;
  449.             if (TIFFReadTile(tif, b, col, row,0,2) < 0 && stoponerr)
  450.                 break;
  451.             if (col + tw > w) {
  452.                 /*
  453.                  * Tile is clipped horizontally.  Calculate
  454.                  * visible portion and skewing factors.
  455.                  */
  456.                 u_long npix = w - col;
  457.                 fromskew = tw - npix;
  458.                 (*put)(raster + y*w + col, r, g, b, Map,
  459.                     npix, nrow, fromskew, toskew + fromskew);
  460.             } else
  461.                 (*put)(raster + y*w + col, r, g, b, Map,
  462.                     tw, nrow, 0, toskew);
  463.         }
  464.         y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
  465.     }
  466.     _TIFFfree(buf);
  467.     return (1);
  468. }
  469.  
  470. /*
  471.  * Get a strip-organized image that has
  472.  *    PlanarConfiguration contiguous if SamplesPerPixel > 1
  473.  * or
  474.  *    SamplesPerPixel == 1
  475.  */    
  476. static int
  477. DECLARE5(gtStripContig,
  478.     TIFF*, tif, u_long*, raster, RGBvalue*, Map, u_long, h, u_long, w)
  479. {
  480.     u_long row, y, nrow;
  481.     u_char *buf;
  482.     tileContigRoutine put;
  483.     u_long rowsperstrip;
  484.     u_long imagewidth;
  485.     u_long scanline;
  486.     int fromskew, toskew;
  487.  
  488.     put = pickTileContigCase(tif, Map);
  489.     if (put == 0)
  490.         return (0);
  491.     buf = (u_char *)_TIFFmalloc(TIFFStripSize(tif));
  492.     if (buf == 0) {
  493.         TIFFError(TIFFFileName(tif), "No space for strip buffer");
  494.         return (0);
  495.     }
  496.     y = setorientation(tif, h);
  497.     toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
  498.     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
  499.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth);
  500.     scanline = TIFFScanlineSize(tif);
  501.     fromskew = (w < imagewidth ? imagewidth - w : 0);
  502.     for (row = 0; row < h; row += rowsperstrip) {
  503.         nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
  504.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
  505.             buf, nrow*scanline) < 0 && stoponerr)
  506.             break;
  507.         (*put)(raster + y*w, buf, Map, w, nrow, fromskew, toskew);
  508.         y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
  509.     }
  510.     _TIFFfree(buf);
  511.     return (1);
  512. }
  513.  
  514. /*
  515.  * Get a strip-organized image with
  516.  *     SamplesPerPixel > 1
  517.  *     PlanarConfiguration separated
  518.  * We assume that all such images are RGB.
  519.  */
  520. static int
  521. DECLARE5(gtStripSeparate,
  522.     TIFF*, tif, u_long*, raster, RGBvalue*, Map, u_long, h, u_long, w)
  523. {
  524.     u_char *buf;
  525.     u_char *r, *g, *b;
  526.     u_long row, y, nrow;
  527.     u_long scanline;
  528.     tileSeparateRoutine put;
  529.     u_long rowsperstrip;
  530.     u_long imagewidth;
  531.     u_long stripsize;
  532.     int fromskew, toskew;
  533.  
  534.     stripsize = TIFFStripSize(tif);
  535.     r = buf = (u_char *)_TIFFmalloc(3*stripsize);
  536.     if (buf == 0)
  537.         return (0);
  538.     g = r + stripsize;
  539.     b = g + stripsize;
  540.     put = pickTileSeparateCase(tif, Map);
  541.     if (put == 0) {
  542.         TIFFError(TIFFFileName(tif), "Can not handle format");
  543.         return (0);
  544.     }
  545.     y = setorientation(tif, h);
  546.     toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
  547.     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
  548.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth);
  549.     scanline = TIFFScanlineSize(tif);
  550.     fromskew = (w < imagewidth ? imagewidth - w : 0);
  551.     for (row = 0; row < h; row += rowsperstrip) {
  552.         nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
  553.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
  554.             r, nrow*scanline) < 0 && stoponerr)
  555.             break;
  556.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1),
  557.             g, nrow*scanline) < 0 && stoponerr)
  558.             break;
  559.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2),
  560.             b, nrow*scanline) < 0 && stoponerr)
  561.             break;
  562.         (*put)(raster + y*w, r, g, b, Map, w, nrow, fromskew, toskew);
  563.         y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
  564.     }
  565.     _TIFFfree(buf);
  566.     return (1);
  567. }
  568.  
  569. #define    PACK(r,g,b)    ((u_long)(r)|((u_long)(g)<<8)|((u_long)(b)<<16))
  570.  
  571. /*
  572.  * Greyscale images with less than 8 bits/sample are handled
  573.  * with a table to avoid lots of shifts and masks.  The table
  574.  * is setup so that put*bwtile (below) can retrieve 8/bitspersample
  575.  * pixel values simply by indexing into the table with one
  576.  * number.
  577.  */
  578. static int
  579. DECLARE2(makebwmap, TIFF*, tif, RGBvalue*, Map)
  580. {
  581.     register int i;
  582.     int nsamples = 8 / bitspersample;
  583.     register u_long *p;
  584.  
  585.     BWmap = (u_long **)_TIFFmalloc(
  586.         256*sizeof (u_long *)+(256*nsamples*sizeof(u_long)));
  587.     if (BWmap == NULL) {
  588.         TIFFError(TIFFFileName(tif), "No space for B&W mapping table");
  589.         return (0);
  590.     }
  591.     p = (u_long *)(BWmap + 256);
  592.     for (i = 0; i < 256; i++) {
  593.         BWmap[i] = p;
  594.         switch (bitspersample) {
  595.             register RGBvalue c;
  596. #define    GREY(x)    c = Map[x]; *p++ = PACK(c,c,c);
  597.         case 1:
  598.             GREY(i>>7);
  599.             GREY((i>>6)&1);
  600.             GREY((i>>5)&1);
  601.             GREY((i>>4)&1);
  602.             GREY((i>>3)&1);
  603.             GREY((i>>2)&1);
  604.             GREY((i>>1)&1);
  605.             GREY(i&1);
  606.             break;
  607.         case 2:
  608.             GREY(i>>6);
  609.             GREY((i>>4)&3);
  610.             GREY((i>>2)&3);
  611.             GREY(i&3);
  612.             break;
  613.         case 4:
  614.             GREY(i>>4);
  615.             GREY(i&0xf);
  616.             break;
  617.         case 8:
  618.             GREY(i);
  619.             break;
  620.         }
  621. #undef    GREY
  622.     }
  623.     return (1);
  624. }
  625.  
  626. /*
  627.  * Palette images with <= 8 bits/sample are handled
  628.  * with a table to avoid lots of shifts and masks.  The table
  629.  * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
  630.  * pixel values simply by indexing into the table with one
  631.  * number.
  632.  */
  633. static int
  634. DECLARE4(makecmap, TIFF*, tif, u_short*, rmap, u_short*, gmap, u_short*, bmap)
  635. {
  636.     register int i;
  637.     int nsamples = 8 / bitspersample;
  638.     register u_long *p;
  639.  
  640.     PALmap = (u_long **)_TIFFmalloc(
  641.         256*sizeof (u_long *)+(256*nsamples*sizeof(u_long)));
  642.     if (PALmap == NULL) {
  643.         TIFFError(TIFFFileName(tif), "No space for Palette mapping table");
  644.         return (0);
  645.     }
  646.     p = (u_long *)(PALmap + 256);
  647.     for (i = 0; i < 256; i++) {
  648.         PALmap[i] = p;
  649. #define    CMAP(x)    \
  650. c = x; *p++ = PACK(rmap[c]&0xff, gmap[c]&0xff, bmap[c]&0xff);
  651.         switch (bitspersample) {
  652.             register RGBvalue c;
  653.         case 1:
  654.             CMAP(i>>7);
  655.             CMAP((i>>6)&1);
  656.             CMAP((i>>5)&1);
  657.             CMAP((i>>4)&1);
  658.             CMAP((i>>3)&1);
  659.             CMAP((i>>2)&1);
  660.             CMAP((i>>1)&1);
  661.             CMAP(i&1);
  662.             break;
  663.         case 2:
  664.             CMAP(i>>6);
  665.             CMAP((i>>4)&3);
  666.             CMAP((i>>2)&3);
  667.             CMAP(i&3);
  668.             break;
  669.         case 4:
  670.             CMAP(i>>4);
  671.             CMAP(i&0xf);
  672.             break;
  673.         case 8:
  674.             CMAP(i);
  675.             break;
  676.         }
  677. #undef CMAP
  678.     }
  679.     return (1);
  680. }
  681.  
  682. /*
  683.  * The following routines move decoded data returned
  684.  * from the TIFF library into rasters filled with packed
  685.  * ABGR pixels (i.e. suitable for passing to lrecwrite.)
  686.  *
  687.  * The routines have been created according to the most
  688.  * important cases and optimized.  pickTileContigCase and
  689.  * pickTileSeparateCase analyze the parameters and select
  690.  * the appropriate "put" routine to use.
  691.  */
  692. #define    REPEAT8(op)    REPEAT4(op); REPEAT4(op)
  693. #define    REPEAT4(op)    REPEAT2(op); REPEAT2(op)
  694. #define    REPEAT2(op)    op; op
  695. #define    CASE8(x,op)                \
  696.     switch (x) {                \
  697.     case 7: op; case 6: op; case 5: op;    \
  698.     case 4: op; case 3: op; case 2: op;    \
  699.     case 1: op;                \
  700.     }
  701. #define    CASE4(x,op)    switch (x) { case 3: op; case 2: op; case 1: op; }
  702.  
  703. #define    UNROLL8(w, op1, op2) {        \
  704.     register u_long x;        \
  705.     for (x = w; x >= 8; x -= 8) {    \
  706.         op1;            \
  707.         REPEAT8(op2);        \
  708.     }                \
  709.     if (x > 0) {            \
  710.         op1;            \
  711.         CASE8(x,op2);        \
  712.     }                \
  713. }
  714. #define    UNROLL4(w, op1, op2) {        \
  715.     register u_long x;        \
  716.     for (x = w; x >= 4; x -= 4) {    \
  717.         op1;            \
  718.         REPEAT4(op2);        \
  719.     }                \
  720.     if (x > 0) {            \
  721.         op1;            \
  722.         CASE4(x,op2);        \
  723.     }                \
  724. }
  725. #define    UNROLL2(w, op1, op2) {        \
  726.     register u_long x;        \
  727.     for (x = w; x >= 2; x -= 2) {    \
  728.         op1;            \
  729.         REPEAT2(op2);        \
  730.     }                \
  731.     if (x) {            \
  732.         op1;            \
  733.         op2;            \
  734.     }                \
  735. }
  736.             
  737.  
  738. #define    SKEW(r,g,b,skew)    { r += skew; g += skew; b += skew; }
  739.  
  740. #if USE_PROTOTYPES
  741. #define    DECLAREContigPutFunc(name) \
  742. static void name(\
  743.     u_long* cp, \
  744.     u_char* pp, \
  745.     RGBvalue* Map, \
  746.     u_long w, u_long h, \
  747.     int fromskew, int toskew \
  748. )
  749. #else
  750. #define    DECLAREContigPutFunc(name) \
  751. static void name(cp, pp, Map, w, h, fromskew, toskew)\
  752.     u_long* cp; \
  753.     u_char* pp; \
  754.     RGBvalue* Map; \
  755.     u_long w; u_long h; \
  756.     int fromskew; int toskew;
  757. #endif
  758.  
  759. /*
  760.  * 8-bit palette => colormap/RGB
  761.  */
  762. DECLAREContigPutFunc(put8bitcmaptile)
  763. {
  764.     while (h-- > 0) {
  765.         UNROLL8(w, NULL, *cp++ = PALmap[*pp++][0]);
  766.         cp += toskew;
  767.         pp += fromskew;
  768.     }
  769. }
  770.  
  771. /*
  772.  * 4-bit palette => colormap/RGB
  773.  */
  774. DECLAREContigPutFunc(put4bitcmaptile)
  775. {
  776.     register u_long *bw;
  777.  
  778.     fromskew /= 2;
  779.     while (h-- > 0) {
  780.         UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
  781.         cp += toskew;
  782.         pp += fromskew;
  783.     }
  784. }
  785.  
  786. /*
  787.  * 2-bit palette => colormap/RGB
  788.  */
  789. DECLAREContigPutFunc(put2bitcmaptile)
  790. {
  791.     register u_long *bw;
  792.  
  793.     fromskew /= 4;
  794.     while (h-- > 0) {
  795.         UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
  796.         cp += toskew;
  797.         pp += fromskew;
  798.     }
  799. }
  800.  
  801. /*
  802.  * 1-bit palette => colormap/RGB
  803.  */
  804. DECLAREContigPutFunc(put1bitcmaptile)
  805. {
  806.     register u_long *bw;
  807.  
  808.     fromskew /= 8;
  809.     while (h-- > 0) {
  810.         UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
  811.         cp += toskew;
  812.         pp += fromskew;
  813.     }
  814. }
  815.  
  816. /*
  817.  * 8-bit greyscale => colormap/RGB
  818.  */
  819. DECLAREContigPutFunc(putgreytile)
  820. {
  821.     while (h-- > 0) {
  822.         register u_long x;
  823.         for (x = w; x-- > 0;)
  824.             *cp++ = BWmap[*pp++][0];
  825.         cp += toskew;
  826.         pp += fromskew;
  827.     }
  828. }
  829.  
  830. /*
  831.  * 1-bit bilevel => colormap/RGB
  832.  */
  833. DECLAREContigPutFunc(put1bitbwtile)
  834. {
  835.     register u_long *bw;
  836.  
  837.     fromskew /= 8;
  838.     while (h-- > 0) {
  839.         UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
  840.         cp += toskew;
  841.         pp += fromskew;
  842.     }
  843. }
  844.  
  845. /*
  846.  * 2-bit greyscale => colormap/RGB
  847.  */
  848. DECLAREContigPutFunc(put2bitbwtile)
  849. {
  850.     register u_long *bw;
  851.  
  852.     fromskew /= 4;
  853.     while (h-- > 0) {
  854.         UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
  855.         cp += toskew;
  856.         pp += fromskew;
  857.     }
  858. }
  859.  
  860. /*
  861.  * 4-bit greyscale => colormap/RGB
  862.  */
  863. DECLAREContigPutFunc(put4bitbwtile)
  864. {
  865.     register u_long *bw;
  866.  
  867.     fromskew /= 2;
  868.     while (h-- > 0) {
  869.         UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
  870.         cp += toskew;
  871.         pp += fromskew;
  872.     }
  873. }
  874.  
  875. /*
  876.  * 8-bit packed samples => RGB
  877.  */
  878. DECLAREContigPutFunc(putRGBcontig8bittile)
  879. {
  880.     fromskew *= samplesperpixel;
  881.     if (Map) {
  882.         while (h-- > 0) {
  883.             register u_long x;
  884.             for (x = w; x-- > 0;) {
  885.                 *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
  886.                 pp += samplesperpixel;
  887.             }
  888.             pp += fromskew;
  889.             cp += toskew;
  890.         }
  891.     } else {
  892.         while (h-- > 0) {
  893.             UNROLL8(w, NULL,
  894.                 *cp++ = PACK(pp[0], pp[1], pp[2]);
  895.                 pp += samplesperpixel);
  896.             cp += toskew;
  897.             pp += fromskew;
  898.         }
  899.     }
  900. }
  901.  
  902. /*
  903.  * 16-bit packed samples => RGB
  904.  */
  905. DECLAREContigPutFunc(putRGBcontig16bittile)
  906. {
  907.     register u_short *wp = (u_short *)pp;
  908.     register u_int x;
  909.  
  910.     fromskew *= samplesperpixel;
  911.     if (Map) {
  912.         while (h-- > 0) {
  913.             for (x = w; x-- > 0;) {
  914.                 *cp++ = PACK(Map[wp[0]], Map[wp[1]], Map[wp[2]]);
  915.                 wp += samplesperpixel;
  916.             }
  917.             cp += toskew;
  918.             wp += fromskew;
  919.         }
  920.     } else {
  921.         while (h-- > 0) {
  922.             for (x = w; x-- > 0;) {
  923.                 *cp++ = PACK(wp[0], wp[1], wp[2]);
  924.                 wp += samplesperpixel;
  925.             }
  926.             cp += toskew;
  927.             wp += fromskew;
  928.         }
  929.     }
  930. }
  931.  
  932. /*
  933.  * 8-bit packed CMYK samples => RGB
  934.  *
  935.  * NB: The conversion of CMYK->RGB is *very* crude.
  936.  */
  937. DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
  938. {
  939.     u_short r, g, b, k;
  940.  
  941.     fromskew *= samplesperpixel;
  942.     if (Map) {
  943.         while (h-- > 0) {
  944.             register u_long x;
  945.             for (x = w; x-- > 0;) {
  946.                 k = 255 - pp[3];
  947.                 r = (k*(255-pp[0]))/255;
  948.                 g = (k*(255-pp[1]))/255;
  949.                 b = (k*(255-pp[2]))/255;
  950.                 *cp++ = PACK(Map[r], Map[g], Map[b]);
  951.                 pp += samplesperpixel;
  952.             }
  953.             pp += fromskew;
  954.             cp += toskew;
  955.         }
  956.     } else {
  957.         while (h-- > 0) {
  958.             UNROLL8(w, NULL,
  959.                 k = 255 - pp[3];
  960.                 r = (k*(255-pp[0]))/255;
  961.                 g = (k*(255-pp[1]))/255;
  962.                 b = (k*(255-pp[2]))/255;
  963.                 *cp++ = PACK(r, g, b);
  964.                 pp += samplesperpixel);
  965.             cp += toskew;
  966.             pp += fromskew;
  967.         }
  968.     }
  969. }
  970.  
  971. #if USE_PROTOTYPES
  972. #define    DECLARESepPutFunc(name) \
  973. static void name(\
  974.     u_long* cp, \
  975.     u_char* r, u_char* g, u_char* b, \
  976.     RGBvalue* Map, \
  977.     u_long w, u_long h, \
  978.     int fromskew, int toskew \
  979. )
  980. #else
  981. #define    DECLARESepPutFunc(name) \
  982. static void name(cp, r, g, b, Map, w, h, fromskew, toskew)\
  983.     u_long* cp; \
  984.     u_char* r; u_char* g; u_char* b; \
  985.     RGBvalue* Map; \
  986.     u_long w; u_long h; \
  987.     int fromskew; int toskew;
  988. #endif
  989.  
  990. /*
  991.  * 8-bit unpacked samples => RGB
  992.  */
  993. DECLARESepPutFunc(putRGBseparate8bittile)
  994. {
  995.     if (Map) {
  996.         while (h-- > 0) {
  997.             register u_long x;
  998.             for (x = w; x > 0; x--)
  999.                 *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]);
  1000.             SKEW(r, g, b, fromskew);
  1001.             cp += toskew;
  1002.         }
  1003.     } else {
  1004.         while (h-- > 0) {
  1005.             UNROLL8(w, NULL, *cp++ = PACK(*r++, *g++, *b++));
  1006.             SKEW(r, g, b, fromskew);
  1007.             cp += toskew;
  1008.         }
  1009.     }
  1010. }
  1011.  
  1012. /*
  1013.  * 16-bit unpacked samples => RGB
  1014.  */
  1015. DECLARESepPutFunc(putRGBseparate16bittile)
  1016. {
  1017.     register u_short *wr = (u_short *)r;
  1018.     register u_short *wg = (u_short *)g;
  1019.     register u_short *wb = (u_short *)b;
  1020.     register u_long x;
  1021.  
  1022.     if (Map) {
  1023.         while (h-- > 0) {
  1024.             for (x = w; x > 0; x--)
  1025.                 *cp++ = PACK(Map[*wr++],Map[*wg++],Map[*wb++]);
  1026.             SKEW(wr, wg, wb, fromskew);
  1027.             cp += toskew;
  1028.         }
  1029.     } else {
  1030.         while (h-- > 0) {
  1031.             for (x = 0; x < w; x++)
  1032.                 *cp++ = PACK(*wr++, *wg++, *wb++);
  1033.             SKEW(wr, wg, wb, fromskew);
  1034.             cp += toskew;
  1035.         }
  1036.     }
  1037. }
  1038.  
  1039. #define    Code2V(c, RB, RW, CR)    ((((c)-RB)*(float)CR)/(float)(RW-RB))
  1040. #define    CLAMP(f,min,max) \
  1041.     (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
  1042.  
  1043. #define    LumaRed        YCbCrCoeffs[0]
  1044. #define    LumaGreen    YCbCrCoeffs[1]
  1045. #define    LumaBlue    YCbCrCoeffs[2]
  1046.  
  1047. static    float D1, D2;
  1048. static    float D3, D4;
  1049.  
  1050. static void
  1051. initYCbCrConversion()
  1052. {
  1053.     D1 = 2 - 2*LumaRed;
  1054.     D2 = D1*LumaRed / LumaGreen;
  1055.     D3 = 2 - 2*LumaBlue;
  1056.     D4 = D2*LumaBlue / LumaGreen;
  1057. }
  1058.  
  1059. static void
  1060. #if USE_PROTOTYPES
  1061. putRGBContigYCbCrClump(
  1062.     register u_long *cp, register u_char *pp,
  1063.     int cw, int ch,
  1064.     u_long w,
  1065.     int n, int fromskew, int toskew
  1066. )
  1067. #else
  1068. putRGBContigYCbCrClump(cp, pp, cw, ch, w, n, fromskew, toskew)
  1069.     register u_long *cp;
  1070.     register u_char *pp;
  1071.     int cw, ch;
  1072.     u_long w;
  1073.     int n, fromskew, toskew;
  1074. #endif
  1075. {
  1076.     float Cb, Cr;
  1077.     int j, k;
  1078.  
  1079.     Cb = Code2V(pp[n],   refBlackWhite[2], refBlackWhite[3], 127);
  1080.     Cr = Code2V(pp[n+1], refBlackWhite[4], refBlackWhite[5], 127);
  1081.     for (j = 0; j < ch; j++) {
  1082.         for (k = 0; k < cw; k++) {
  1083.             float Y, R, G, B;
  1084.             Y = Code2V(*pp++,
  1085.                 refBlackWhite[0], refBlackWhite[1], 255);
  1086.             R = Y + Cr*D1;
  1087.             B = Y + Cb*D3;
  1088.             G = Y - Cb*D4 - Cr*D2;
  1089.             cp[k] = PACK(CLAMP(R,0,255),
  1090.                      CLAMP(G,0,255),
  1091.                      CLAMP(B,0,255));
  1092.         }
  1093.         cp += w+toskew;
  1094.         pp += fromskew;
  1095.     }
  1096. }
  1097. #undef LumaBlue
  1098. #undef LumaGreen
  1099. #undef LumaRed
  1100. #undef CLAMP
  1101. #undef Code2V
  1102.  
  1103. /*
  1104.  * 8-bit packed YCbCr samples => RGB
  1105.  */
  1106. DECLAREContigPutFunc(putcontig8bitYCbCrtile)
  1107. {
  1108.     u_int Coff = YCbCrVertSampling * YCbCrHorizSampling;
  1109.     u_long *tp;
  1110.     u_long x;
  1111.  
  1112.     /* XXX adjust fromskew */
  1113.     while (h >= YCbCrVertSampling) {
  1114.         tp = cp;
  1115.         for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
  1116.             putRGBContigYCbCrClump(tp, pp,
  1117.                 YCbCrHorizSampling, YCbCrVertSampling,
  1118.                 w, Coff, 0, toskew);
  1119.             tp += YCbCrHorizSampling;
  1120.             pp += Coff+2;
  1121.         }
  1122.         if (x > 0) {
  1123.             putRGBContigYCbCrClump(tp, pp,
  1124.                 x, YCbCrVertSampling,
  1125.                 w, Coff, YCbCrHorizSampling - x, toskew);
  1126.             pp += Coff+2;
  1127.         }
  1128.         cp += YCbCrVertSampling*(w + toskew);
  1129.         pp += fromskew;
  1130.         h -= YCbCrVertSampling;
  1131.     }
  1132.     if (h > 0) {
  1133.         tp = cp;
  1134.         for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
  1135.             putRGBContigYCbCrClump(tp, pp, YCbCrHorizSampling, h,
  1136.                 w, Coff, 0, toskew);
  1137.             tp += YCbCrHorizSampling;
  1138.             pp += Coff+2;
  1139.         }
  1140.         if (x > 0)
  1141.             putRGBContigYCbCrClump(tp, pp, x, h,
  1142.                 w, Coff, YCbCrHorizSampling - x, toskew);
  1143.     }
  1144. }
  1145.  
  1146. /*
  1147.  * Select the appropriate conversion routine for packed data.
  1148.  */
  1149. static tileContigRoutine
  1150. DECLARE2(pickTileContigCase, TIFF*, tif, RGBvalue*, Map)
  1151. {
  1152.     tileContigRoutine put = 0;
  1153.  
  1154.     switch (photometric) {
  1155.     case PHOTOMETRIC_RGB:
  1156.         if (bitspersample == 8)
  1157.             put = putRGBcontig8bittile;
  1158.         else
  1159.             put = putRGBcontig16bittile;
  1160.         break;
  1161.     case PHOTOMETRIC_SEPARATED:
  1162.         if (bitspersample == 8)
  1163.             put = putRGBcontig8bitCMYKtile;
  1164.         break;
  1165.     case PHOTOMETRIC_PALETTE:
  1166.         switch (bitspersample) {
  1167.         case 8:    put = put8bitcmaptile; break;
  1168.         case 4: put = put4bitcmaptile; break;
  1169.         case 2: put = put2bitcmaptile; break;
  1170.         case 1: put = put1bitcmaptile; break;
  1171.         }
  1172.         break;
  1173.     case PHOTOMETRIC_MINISWHITE:
  1174.     case PHOTOMETRIC_MINISBLACK:
  1175.         switch (bitspersample) {
  1176.         case 8:    put = putgreytile; break;
  1177.         case 4: put = put4bitbwtile; break;
  1178.         case 2: put = put2bitbwtile; break;
  1179.         case 1: put = put1bitbwtile; break;
  1180.         }
  1181.         break;
  1182.     case PHOTOMETRIC_YCBCR:
  1183.         switch (bitspersample) {
  1184.         case 8: put = putcontig8bitYCbCrtile; break;
  1185.         }
  1186.         break;
  1187.     }
  1188.     if (put == 0)
  1189.         TIFFError(TIFFFileName(tif), "Can not handle format");
  1190.     return (put);
  1191. }
  1192.  
  1193. /*
  1194.  * Select the appropriate conversion routine for unpacked data.
  1195.  *
  1196.  * NB: we assume that unpacked single channel data is directed
  1197.  *     to the "packed routines.
  1198.  */
  1199. static tileSeparateRoutine
  1200. DECLARE2(pickTileSeparateCase, TIFF*, tif, RGBvalue*, Map)
  1201. {
  1202.     tileSeparateRoutine put = 0;
  1203.  
  1204.     switch (photometric) {
  1205.     case PHOTOMETRIC_RGB:
  1206.         if (bitspersample == 8)
  1207.             put = putRGBseparate8bittile;
  1208.         else
  1209.             put = putRGBseparate16bittile;
  1210.         break;
  1211.     }
  1212.     if (put == 0)
  1213.         TIFFError(TIFFFileName(tif), "Can not handle format");
  1214.     return (put);
  1215. }
  1216.